<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>头像裁剪案例</title>
    <style>
        html, body {
            margin: 5px;
            padding: 0;
        }
    </style>
</head>
<body>
<div style="width: 500px;height: 500px;border: 1px solid black;position: relative;float: left;">
    <canvas id="background" width="500" height="500" style="position: absolute;">
        浏览器不支持Canvas……
    </canvas>
    <canvas id="selector" width="500" height="500" style="position: absolute;">
        浏览器不支持Canvas……
    </canvas>
</div>
<div style="float: left;">
    <canvas width="500" height="500" id="preview"></canvas>
</div>
<div style="float: left;">
    <img style="width: 250px;height: 250px;" alt="" id="img">
</div>
<div style="clear: both;float: left;">
    <input type="file" id="file">
</div>
<script>
    var backgroundCanvas = document.getElementById('background');
    var selectorCanvas = document.getElementById('selector');
    var previewCanvas = document.getElementById('preview');
    var imgElem = document.getElementById('img');
    var imageData;

    function getImage(cvs) {
        var ctx = cvs.getContext('2d');

        // 文件上传控件
        var fileInput = document.getElementById('file');

        // 用户选择文件之后，会发生change事件，监听这个事件
        fileInput.addEventListener('change', function () {

            var imageFile = fileInput.files[0];

            // 用于把file对象转换成一个当前页面里可以使用的url。记住就行。
            var url = URL.createObjectURL(imageFile);

            var img = new Image();
            img.src = url;
            img.addEventListener('load', function () {
                // 图像加载之后执行：使图像正好占满屏幕又不改变缩放的大小
                var w = img.width;
                var h = img.height;
                var scaleX = 500 / w;
                var scaleY = 500 / h;
                var scale = scaleX < scaleY ? scaleX : scaleY;

                ctx.save();
                ctx.translate(250, 250);
                ctx.scale(scale, scale); // 对坐标系进行缩放
                ctx.drawImage(img, -w / 2, -h / 2);

                ctx.restore();
            })
        });
    }
    getImage(backgroundCanvas);

    function selectSquare(selectorCanvas, previewCanvas, backgroundCanvas) {
        var ctx = selectorCanvas.getContext('2d');


        var selector = {
            x: 0,
            y: 0,
            l: 0, // 因为是正方形，所以没有长宽，只有边长
            dragX: 0,
            dragY: 0,
            draw: function () {
                ctx.save();
                ctx.fillStyle = 'rgba(0,0,0,0.5)'; // 半透明的黑色
                ctx.clearRect(0, 0, 500, 500);
                ctx.fillRect(0, 0, 500, 500);
                ctx.clearRect(this.x, this.y, this.l, this.l);
                ctx.restore();
            }
        };

        var state = '闲置';


        function preview() {
            var ctxPreview = previewCanvas.getContext('2d');
            ctxPreview.clearRect(0, 0, 500, 500);
            ctxPreview.drawImage(backgroundCanvas,
                    selector.x, selector.y, selector.l, selector.l,
                    0, 0, 500, 500);
            /*
             toDataURL()方法
             此函数，返回一张使用canvas绘制的图片，返回值符合data:URL格式，格式如下：
             url = canvas . toDataURL( [ type, ... ])
             规范规定，在未指定返回图片类型时，返回的图片格式必须为PNG格式，
             type的可以在image/png，image/jpeg,image/svg+xml等 MIME类型中选择。
             如果是image/jpeg，可以有第二个参数，如果第二个参数的值在0-1之间，则表示JPEG的质量等级，否则使用浏览器内置默认质量等级。
             */
            var dataurl = previewCanvas.toDataURL('image/jpeg', 0.1);
            imgElem.src = dataurl;
        }

        selectorCanvas.addEventListener('mousedown', function (evt) {
            var x = evt.offsetX;
            var y = evt.offsetY;
            if (state == '闲置') {
                selector.x = x;
                selector.y = y;
                state = '选择中'
            } else if (state == '选择结束') {
                // 判断鼠标是不是点在选择器里面
                ctx.beginPath();
                ctx.rect(selector.x, selector.y, selector.l, selector.l);
                var inPath = ctx.isPointInPath(x, y);

                if (inPath) { // 如果鼠标点在选择器里面,则开始准备拖动
                    selector.dragX = x;
                    selector.dragY = y;
                    state = "拖动中";
                } else { // 如果鼠标点在选择器外面则清空屏幕，让选择器恢复闲置状态
                    ctx.clearRect(0, 0, 500, 500);
                    state = "闲置";
                }
            }
        });
        selectorCanvas.addEventListener('mousemove', function (evt) {
            evt.preventDefault(); // 阻止浏览器的默认行为
            var x = evt.offsetX;
            var y = evt.offsetY;
            if (state == '选择中') {
                var w = x - selector.x;
                var h = y - selector.y;
                selector.l = w > h ? w : h;
                selector.draw();
            } else if (state == '拖动中') {
                // 得到拖动过程中，“两帧之间”鼠标移动的距离
                var moveX = x - selector.dragX;
                var moveY = y - selector.dragY;
                // 根据移动的距离改变选择器的位置
                selector.x = selector.x + moveX;
                selector.y = selector.y + moveY;

                selector.draw();
                // 记录这一帧时鼠标的位置
                selector.dragX = x;
                selector.dragY = y;
            }

        });
        selectorCanvas.addEventListener('mouseup', function (evt) {
            var x = evt.offsetX;
            var y = evt.offsetY;
            if (state == '选择中') {
                var w = x - selector.x;
                var h = y - selector.y;
                selector.l = w > h ? w : h;
                selector.draw();
                state = '选择结束'
                preview();
            } else if (state == '拖动中') {
                // 拖动结束之后，重置状态到选择结束
                state = '选择结束';
                preview();
            }
        });

        setInterval(function(){console.log(state)},100)
    }
    selectSquare(selectorCanvas, previewCanvas, backgroundCanvas);


</script>
</body>
</html>